mod macros;
use std::vec;

use serde::{Deserialize, Serialize};
use uuid::Uuid;

pub use macros::*;

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
pub struct ServerInfo {
    pub name: String,
    pub tcp_ports: Vec<u16>,
    pub udp_ports: Vec<u16>,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
pub struct NetemProfile {
    pub id: Uuid,
    pub name: String,
    pub cfgs: Vec<NetemConfig>,
    pub active: bool,
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum DelayConfig {
    Value(i16),
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum JitterConfig {
    Stable(i16),
    Burst { burst: i16, interval: i32 },
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum LossConfig {
    Stable(f32),
    Poisson(f32),
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum NetemConfig {
    Delay(DelayConfig),
    Jitter(JitterConfig),
    Loss(LossConfig),
}

impl From<DelayConfig> for NetemConfig {
    fn from(value: DelayConfig) -> Self {
        NetemConfig::Delay(value)
    }
}

impl From<JitterConfig> for NetemConfig {
    fn from(value: JitterConfig) -> Self {
        NetemConfig::Jitter(value)
    }
}

impl From<LossConfig> for NetemConfig {
    fn from(value: LossConfig) -> Self {
        NetemConfig::Loss(value)
    }
}

impl ServerInfo {
    pub fn format_title(&self) -> String {
        format!("{} 网络设置", self.name)
    }
    pub fn format_detail(&self) -> String {
        let mut sections: Vec<String> = Vec::new();
        for port in self.tcp_ports.iter() {
            sections.push(format!("TCP/{}", port));
        }
        for port in self.udp_ports.iter() {
            sections.push(format!("UDP/{}", port));
        }
        sections.join(" ")
    }
}

impl NetemProfile {
    pub fn delay(&self) -> i16 {
        for cfg in self.cfgs.iter() {
            match cfg {
                NetemConfig::Delay(DelayConfig::Value(val)) => return *val,
                _ => (),
            }
        }
        0
    }
    pub fn loss(&self) -> f32 {
        for cfg in self.cfgs.iter() {
            match cfg {
                NetemConfig::Loss(LossConfig::Stable(val)) => return *val,
                NetemConfig::Loss(LossConfig::Poisson(val)) => return *val,
                _ => (),
            }
        }
        0.0
    }
    pub fn is_poisson_loss(&self) -> bool {
        for cfg in self.cfgs.iter() {
            match cfg {
                NetemConfig::Loss(LossConfig::Poisson(_)) => return true,
                _ => (),
            }
        }
        false
    }
    pub fn jitter(&self) -> i16 {
        for cfg in self.cfgs.iter() {
            match cfg {
                NetemConfig::Jitter(JitterConfig::Stable(val)) => return *val,
                _ => (),
            }
        }
        0
    }
    pub fn burst(&self) -> (i16, i32) {
        for cfg in self.cfgs.iter() {
            match cfg {
                NetemConfig::Jitter(JitterConfig::Burst { burst, interval }) => {
                    return (*burst, *interval)
                }
                _ => (),
            }
        }
        (0, 30_000)
    }
    pub fn presets() -> Vec<Self> {
        vec![
            NetemProfile {
                name: String::from("无损伤"),
                cfgs: vec![],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("10% 均匀丢包"),
                cfgs: vec![
                    LossConfig::Stable(0.1).into(),
                ],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("30% 均匀丢包"),
                cfgs: vec![
                    LossConfig::Stable(0.3).into(),
                ],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("50% 均匀丢包"),
                cfgs: vec![
                    LossConfig::Stable(0.5).into(),
                ],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("10% 非均匀丢包"),
                cfgs: vec![
                    LossConfig::Poisson(0.1).into(),
                ],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("公司差 Wifi"),
                cfgs: vec![
                    DelayConfig::Value(90).into(),
                    LossConfig::Poisson(0.05).into(),
                    JitterConfig::Burst {
                        burst: 400,
                        interval: 30_000,
                    }
                    .into(),
                ],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("天津XQL 4G"),
                cfgs: vec![
                    DelayConfig::Value(40).into(),
                    JitterConfig::Stable(25).into(),
                    JitterConfig::Burst {
                        burst: 420,
                        interval: 30_000,
                    }
                    .into(),
                ],
                ..Default::default()
            },
            NetemProfile {
                name: String::from("天津XLZ 5G"),
                cfgs: vec![
                    DelayConfig::Value(30).into(),
                    LossConfig::Poisson(0.01).into(),
                    JitterConfig::Stable(36).into(),
                    JitterConfig::Burst {
                        burst: 700,
                        interval: 30_000,
                    }
                    .into(),
                ],
                ..Default::default()
            },
        ]
    }
}
